package org.jdsm.flow.core.users.impl.jpa.dao;

import org.jdsm.flow.core.users.IGroup;
import org.jdsm.flow.core.users.impl.jpa.Group;
import org.jdsm.flow.core.utils.impl.jpa.GenericDao;
import org.jdsm.flow.core.utils.impl.jpa.PersistenceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.TypedQuery;
import java.util.*;


/**
 * User: mikom
 * Date: 3/14/13
 * Time: 5:12 PM
 */
public class GroupDAO extends GenericDao<Group, Long> {
    private static final Logger log = LoggerFactory.getLogger(GroupDAO.class);

    public IGroup load(IGroup<Long> group) {
        IGroup result = null;
        if (group == null) {
            log.warn("role can't be null");
            return null;
        }
        if (group.getId() != null) {
            result = find(group.getId());
        }
        if (result == null && group.getName() != null) {
            result = findByName(group.getName());
        }
        log.debug("found group: {}", result);
        return result;
    }

    public Collection<IGroup> load(int maxResult, int startResult, boolean isSort, String field) {
        return new LinkedHashSet<IGroup>(PersistenceUtils.loadedByCriteria(getEntityManager(), Group.class, maxResult, startResult, isSort, field));
    }

    public Collection<Group> load(Collection<Long> entityIds){
        List<Group> result = PersistenceUtils.loadEntitiesByIds(getEntityManager(), Group.class, entityIds);
        return new LinkedHashSet<Group>(result);
    }

    public IGroup findByName(String name) {
        log.debug("find group by name: {}", name);
        if (name == null) {
            log.warn("group name is null");
            return null;
        }
        try {
            return getEntityManager().createNamedQuery("group.findGroupByName", Group.class)
                    .setParameter("groupName", name).getSingleResult();
        } catch (NoResultException e) {
            log.warn("could not found group by name:{}", name);
            log.debug("trace: ", e);
            return null;
        } catch (NonUniqueResultException e) {
            log.warn("non unique group by name: {}", name);
            log.debug("trace: ", e);
            return null;
        }
    }

    public Collection<IGroup> findAllowed(Long permission) {
        if (permission == null) {
            log.warn("permission can't be null");
            return Collections.emptySet();
        }
        try {
            TypedQuery<Group> tq = getEntityManager().createNamedQuery("group.findAllowGroups", Group.class)
                    .setParameter("groupPermission", permission);
            List<Group> gs = tq.getResultList();

            Set<IGroup> groups = new HashSet<IGroup>(gs);
            if (log.isDebugEnabled()) {
                for (IGroup iGroup : groups) {
                    log.debug("group in result: {}", iGroup);
                }
            }
            return groups;
        } catch (NoResultException e) {
            log.warn("could not found allowed groups by permission:{}", permission);
            log.debug("trace: ", e);
            return Collections.emptySet();
        }

    }

    public int count() {
        return PersistenceUtils.count(getEntityManager(), Group.class).intValue();
    }

    public IGroup newInstance() {
        return new Group();
    }

    public IGroup newInstance(String groupName, Long permission) {
        Group group = (Group) newInstance();
        group.setName(groupName);
        group.setPermission(permission);
        return group;
    }
}
